/**
 * File: ArrayHelper.java
 * Created by: mhaimel
 * Created on: Mar 9, 2010
 * CVS:  $Id: ArrayHelper.java 1.0 Mar 9, 2010 1:49:05 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.utils;

import java.lang.reflect.Array;

import uk.ac.ebi.curtain.utils.concurrent.CurtainAtomicIntegerArray;
import uk.ac.ebi.curtain.utils.concurrent.CurtainAtomicLongArray;
import uk.ac.ebi.curtain.utils.concurrent.CurtainAtomicReferenceArray;

/**
 * @author mhaimel
 *
 */
public class ArrayHelper {

	@SuppressWarnings("unchecked")
	public static <T> T[] getInitalArray(Integer categories, T defVal) {
		T[] arr =  newArray((Class<T>) defVal.getClass(),categories); 
		for(int i = 0; i < categories; ++i){
			arr[i] = defVal;
		}
		return arr;
	}

	public static <T extends Number> T[] toArray(CurtainAtomicReferenceArray<T> rArr, Class<T> clazz){
		int len = rArr.length();
		T[] arr = newArray(clazz,len);
		for(int i = 0; i < len; ++i){
			arr[i] = rArr.get(i);
		}
		return arr;
	}
	
	public static Integer[] toArray(CurtainAtomicIntegerArray rArr){
		int len = rArr.length();
		Integer[] arr = newArray(Integer.class,len);
		for(int i = 0; i < len; ++i){
			arr[i] = rArr.get(i);
		}
		return arr;
	}
	
	public static Long[] toArray(CurtainAtomicLongArray rArr){
		int len = rArr.length();
		Long[] arr = newArray(Long.class,len);
		for(int i = 0; i < len; ++i){
			arr[i] = rArr.get(i);
		}
		return arr;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T[][] getInitalArray(T defVal, Integer dim1,Integer dim2) {
		T[][] arr =  newArray((Class<T>) defVal.getClass(),dim1,dim2); 
		for(int i = 0; i < dim1; ++i){
			for(int j = 0; j < dim2; ++j){
				arr[i][j] = defVal;
			}
		}
		return arr;
	}
	
	@SuppressWarnings("unchecked")
	private static <T> T[] newArray(Class<T> clazz,Integer len) {
		return (T[]) Array.newInstance(clazz, len);
	}
	
	@SuppressWarnings("unchecked")
	private static <T> T[][] newArray(Class<T> clazz,Integer dim1,Integer dim2) {
		return (T[][]) Array.newInstance(clazz, dim1,dim2);
	}
	
	@SuppressWarnings("unchecked")
	public static <T extends Number> T[] castArray(String[] val, Class<T> clazz){
		int len = val.length;
		T[] arr = (T[]) Array.newInstance(clazz, len);
		if(clazz.equals(Integer.class)){				
			for(int i = 0; i < len; ++i){
				String s = val[i];
				arr[i] = (T) Integer.valueOf(s);
			}
		}else if(clazz.equals(Long.class)){
			for(int i = 0; i < len; ++i){
				String s = val[i];			
				arr[i] = (T) Long.valueOf(s);
			}
		} else if(clazz.equals(Double.class)){
			for(int i = 0; i < len; ++i){
				String s = val[i];			
				arr[i] = (T) Double.valueOf(s);
			}
		} else {
				throw new IllegalArgumentException("Number " + clazz + " not yet supported!");
		}
		return arr;
	}
	
	public static Double incrementAndGet(CurtainAtomicReferenceArray<Double> array, Double incr, Integer cat){
		while(true){
			Double val = array.get(cat);
			Double nVal = val+ incr;
			if(array.compareAndSet(cat,val, nVal)){
				return nVal;
			}
		}
	}
}
